#!/bin/bash
#
# Usage:  observe_pulsar name freq bandwidth gain obs-time longitude
#

function emptyarg
{
	if [ "@@" = $2 ]
	then
		echo "Missing argument for $1"
		exit 1
	fi
}

#
# Establish defaults
#

#
# Figure out where to write output files
#
if [ -e /mnt/extra ]
then
	PREFIX=/mnt/extra/
else
    PREFIX=$HOME/
fi

#
# If this environment variable exists, it overrides previous decisions
#
if [ @$PSR_DATA_LOCATION@ != "@@" ]
then
	PREFIX=${PSR_DATA_LOCATION}/
fi

WIDE=0
NAME=B0329+54
FREQ=408.0
SRATE=4.0
RFGAIN=40
LONGITUDE=-76.03
DSCALE=1
OBSTIME=5
HP=0
HPGAIN=0.6
ROLLOFF=0
SKY=0.0
INTEGRATOR=0
RESOLUTION=1
PROFILE=0
TBINS=200
PINTERVAL=30
GPS=0
TRIALS="-10.0,0.0,10.0"
function do_help
{
			cat <<!EOF!
Usage: $0 <options>:

--name         Pulsar name. Default: $NAME
--freq         Center frequency **IN MHz**.  Default: $FREQ
--srate        Sample rate, **IN MHz**:  Default: $SRATE
--rfgain       RF gain, usually in dB. Default: $RFGAIN
--longitude    Local longitude. Negative is west.: Default: $LONGITUDE
--dscale       Detector scaling: Default: $DSCALE
               NOTE: A negative value here causes it to autoscale to produce
                 output whose average magnitude is '<dscale>'
--wide         Enable Wide (16 bit) samples Default: $WIDE
--hp           Enable high-pass filter. Default: $HP
--hpgain       Set "gain" on high-pass. Default: $HPGAIN
--obstime      Observing time, **MINUTES**. Default: $OBSTIME
               NOTE: A negative 'obstime' results in running immediately
               rather than waiting for the object to enter the FOV.
--prefix       Output file prefix. Default: $PREFIX
--rolloff      Enable roll-off correction. Default: $ROLLOFF
--sky          Specify actual sky frequency. 0 is off Default: $SKY
--integrator   Use integrate-and-dump instead of IIR filter.  Default: $INTEGRATOR
--profile      Enable crude profile output.  Default $PROFILE
--resolution   Increase number of filterbank outputs by this value. Default: $RESOLUTION
--tbins        Number of time-bins for builtin pulsar folding. Default: $TBINS
--pinterval    Interval between pulsar profile logs. Default: $PINTERVAL
--gps          Indicate that there's a GPS module present (UHD/USRP only).
--trials       List of trial PPMs for folder. Default $TRIALS
!EOF!
}

function mhz
{
	retval=`python -c "print $1/1000000.0"`
}

if [ $# -lt 1 ]
then
	do_help
	exit
fi
PATH=$PATH:/usr/local/bin
export PATH

trap "rm -f usrp$$ tmp$$; exit" 1 2 3 4 5 6 7 8 9 10

#
# Check command line args
#

while [ $# -ge 1 ]
do
	case $1 in
	--name)
		emptyarg $1 $2
		NAME=$2
		shift 2
		;;
	--freq)
	    emptyarg $1 $2
		FREQ=$2
		shift 2
		;;
	--srate)
	    emptyarg $1 $2
		SRATE=$2
		shift 2
		;;
	--rfgain)
	    emptyarg $1 $2
		RFGAIN=$2
		shift 2
		;;
	--longitude)
	    emptyarg $1 $2
		LONGITUDE=$2
		shift 2
		;;
	--dscale)
	    emptyarg $1 $2
		DSCALE=$2
		shift 2
		;;
	 --wide)
		WIDE=1
		shift
		;;
	 --hp)
	    HP=1
	    shift
	    ;;
	 --hpgain)
	    emptyarg $1 $2
	    HPGAIN=$2
	    shift 2
	    ;;
	 --obstime)
	    emptyarg $1 $2
	    OBSTIME=$2
	    shift 2
	    ;;
	 --prefix)
		emptyarg $1 $2
		PREFIX=$2
		shift 2
		;;
	--rolloff)
		ROLLOFF=1
		shift
		;;
     --integrator)
		INTEGRATOR=1
		shift
		;;
     --help)
		do_help
        exit
        ;;
     --resolution)
        RESOLUTION=$2
        shift 2
       ;;
     --profile)
       PROFILE=1
       shift
       ;;
     --pinterval)
       PINTERVAL=$2
       shift 2
       ;;
     --tbins)
       TBINS=$2
       shift 2
       ;;
     --gps)
       GPS=1
       shift
       ;;
     --trials)
       TRIALS=$2
       shift 2
       ;;
	 *)
		echo "Unknown argument: $1"
		exit 1
		;;
    esac
done

DEVICE="None"
SRATE=`python -c "print ($SRATE * 1.0e6)"`
FREQ=`python -c "print ($FREQ * 1.0e6)"`
SKY=`python -c "print ($SKY * 1.0e6)"`
OBSTIME=`expr $OBSTIME '*' 60`
SUBDEV="A:A"
SUPPORTED="usrp rtlsdr airspy hackrf limesdr"
PPS=internal
CLOCK=internal


#
# Figure out where the PSR database is
#
DB=/usr/local/share/psr_db.txt
dbfile=$HOME/psr_db.txt
if [ -e ./psr_db.txt ]
then
	dbfile=./psr_db.txt
elif [ -e $HOME/psr_db.txt ]
then
	dbfile=$HOME/psr_db.txt
elif [ -e $DB ]
then
	dbfile=$DB
else
	echo Cannot find PSR database file
	exit
fi
cased=`echo $NAME |tr '[A-Z]' '[a-z]'`
if grep -qi $cased $dbfile
then
	eval `grep $cased $dbfile`
else
	echo "Could not find pulsar params in database for: $NAME"
	exit
fi

#
# Check the USB bus on the system
#

lsusb >tmp$$

#
# Then look for possible SDR devices on USB first
#

#
# UHD USB B200 devices
#
if grep -q '2500:002[0123]' tmp$$
then
   clk=`python -c "print $SRATE*4"`
   DEVICE="type=b200,num_recv_frames=128,master_clock_rate=$clk,subdev='A:A'"
   uhd_usrp_probe --args type=b200 >usrp$$ 2>&1
   SUBDEV="A:A"
   if grep -i -q "Found.*an.*GPSDO" usrp$$
   then
	EXEC=pulsar_filterbank_gps.py
	PPS=external
	CLOCK=gpsdo
   else
    EXEC=pulsar_filterbank_ntp.py
    PPS=internal
    CLOCK=external
   fi
   rm -f usrp$$
#
# RTLSDR
#
elif grep -q "0bda:283[28]" tmp$$
then
  DEVICE="rtl=0"
  EXEC=pulsar_filterbank_none.py
  SRATE=`python -c "rate=$SRATE if $SRATE <= 2560000 else 2560000; print rate"`
#
# AIRSPY
#
elif grep -q "1d50:60a1" tmp$$
then
  DEVICE="airspy=0"
  EXEC=pulsar_filterbank_none.py
#
# HackRF
#
elif grep -q "1d50:6089" tmp$$
then
  DEVICE="hackrf=0"
  EXEC=pulsar_filterbank_none.py
#
# LimeSDR
#
elif grep -q "1d50:6108" tmp$$
then
  DEVICE="soapy,driver=lime"
  EXEC=pulsar_filterbank_none.py
elif grep -q "0403:601f" tmp$$
then
  DEVICE="soapy,driver=lime"
  EXEC=pulsar_filterbank_none.py
fi

rm -f tmp$$

#
# Still nothing from USB scan, try for a net-connected UHD device
#
# Make brash assumptions about inet addy and subdev name
#
if [ $DEVICE = None ]
then
	uhd_find_devices >usrp$$ 2>&1
	if grep -q "Device Address" usrp$$
	then
	    DEVICE="addr=192.168.10.2"
	    SUBDEV="A:0"
	    uhd_usrp_probe --args $DEVICE >usrp$$ 2>&1
	    if grep -i -q "Found an.*GPS" usrp$$
	    then
			EXEC=pulsar_filterbank_gps.py
			PPS=gspdo
			CLOCK=gpsdo
		else
		    EXEC=pulsar_filterbank_ntp.py
		    PPS=internal
		    CLOCK=external
		fi
     fi
     rm -f usrp$$
fi

rm -f usrp$$
rm -f tmp$$

#
# If --gps option present
#
if [ $GPS -ne 0 ]
then
	case $DEVICE in
	*type=b2*|*addr=*)
		PPS=gspdo
		CLOCK=gpsdo
		EXEC=pulsar_filterbank_gps.py
		;;
	*)
		echo "***WARNING: GPS not supported in this device type"
		;;
	esac
fi

if [ $DEVICE = None ]
then
	echo "No supported SDR devices found: $SUPPORTED"
	exit
fi
mhz $FREQ
f=$retval

mhz $SRATE
b=$retval

echo Found $DEVICE tuning to $f MHz with a bandwidth of $b MHz
if [ $OBSTIME -lt 0 ]
then
	echo Running immediately for `python -c "print abs($OBSTIME)"` seconds
else
	echo Will run for $OBSTIME seconds once object is in view
fi
echo Pulsar Parameters: $NAME: PW50 $PW50 DM $DM RA $RA DEC $DEC P0 $P0

#
# Wait for pulsar to "rise" -- to be within obstime/2 of transit
#
if [ $OBSTIME -gt 0 ]
then
	target=`python -c "print ($RA - ($OBSTIME/3600.0)/1.95)"`
	while true
	do
		lmst=`lmst.py $LONGITUDE`
		truth=`python -c "t=True if abs($target-$lmst) <  0.05 else False; print t"`
		if [ $truth = True ]
		then
			echo Starting receiver at $lmst
			break
		fi
		echo Waiting for pulsar $NAME to rise at: $target, current LMST is $lmst
		sleep 15
	done
else
	OBSTIME=`expr $OBSTIME '*' -1`
fi

#
# Call the appropriate version of the Gnu Radio flow-graph
#
echo Executing $EXEC
$EXEC --dec $DEC --ra $RA --device $DEVICE --dm $DM --freq $FREQ  \
   --pps $PPS --prefix $PREFIX --pw50 $PW50 --refclock $CLOCK --rfgain $RFGAIN --runtime $OBSTIME \
   --source $NAME --srate $SRATE --subdev $SUBDEV --rfilist "$RFILIST" --resolution $RESOLUTION \
   --thresh 2.2 --dscale $DSCALE --hp $HP --hpgain $HPGAIN --wide $WIDE --rolloff $ROLLOFF --sky $SKY \
   --p0 $P0 --integrator $INTEGRATOR --profile $PROFILE --pinterval $PINTERVAL --tbins $TBINS \
   --trial-ppms $TRIALS
